package com.dries.portal.module.convener.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.dries.common.api.CommonResult;
import com.dries.common.api.ResultCode;
import com.dries.common.exception.ApiException;
import com.dries.portal.module.chat.constants.ChatConstant;
import com.dries.portal.module.chat.entity.RecentChat;
import com.dries.portal.module.chat.service.IGroupChatService;
import com.dries.portal.module.chat.service.IRecentChatService;
import com.dries.portal.module.convener.dto.ConvenerCreateParams;
import com.dries.portal.module.convener.dto.ConvenerLikesParams;
import com.dries.portal.module.convener.entity.Convener;
import com.dries.portal.module.convener.entity.ConvenerLikes;
import com.dries.portal.module.convener.entity.JoinConvener;
import com.dries.portal.module.convener.enums.ConvenerPaymentType;
import com.dries.portal.module.convener.enums.ConvenerStatus;
import com.dries.portal.module.convener.enums.JoinConvenerType;
import com.dries.portal.module.convener.service.IConvenerLikesService;
import com.dries.portal.module.convener.service.IConvenerService;
import com.dries.portal.module.convener.service.IJoinConvenerService;
import com.dries.portal.module.convener.vo.ConvenerVo;
import com.dries.portal.module.convener.vo.ShopDetailVo;
import com.dries.portal.module.xxshop.vo.UserOrderInfoVo;
import com.dries.security.service.RedisService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.security.Principal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author dries
 * @email samphsanie@gmail.com
 * @date 2020-08-20 15:19:56
 */
@RestController
@Api(tags = "召集令API", value = "ConvenerController")
@RequestMapping("convener")
public class ConvenerController {

    @Resource
    private IConvenerService convenerService;
    @Resource
    private IJoinConvenerService joinConvenerService;
    @Resource
    private IGroupChatService groupChatService;
    @Resource
    private IConvenerLikesService convenerLikesService;
    @Resource
    private IRecentChatService recentChatService;
    @Resource
    private RedisService redisService;

    /**
     * 列表
     */
    @ApiOperation("召集令列表")
    @GetMapping("/list")
    public CommonResult list(Principal principal,
                             @RequestParam(required = false, defaultValue = "1") Integer pageNum,
                             @RequestParam(required = false, defaultValue = "10") Integer pageSize) {

        if (principal.getName() == null) {
            throw new ApiException(ResultCode.UNAUTHORIZED);
        }

        PageHelper.startPage(pageNum, pageSize);
        List<Convener> list = convenerService.list(new QueryWrapper<Convener>().lambda()
                .eq(Convener::getConvenerStatus, ConvenerStatus.NORMAL.getCode())
                .orderByDesc(Convener::getCreateTime)
        );

        if (CollUtil.isNotEmpty(list)) {
            List<Integer> cIds = list.stream().map(Convener::getCid).collect(Collectors.toList());
            List<ConvenerLikes> likes = convenerLikesService.list(new QueryWrapper<ConvenerLikes>().lambda().in(ConvenerLikes::getConvenerId, cIds));
            List<ConvenerVo> convenerVos = list.stream().map(e -> {
                ConvenerVo convenerVo = new ConvenerVo();
                BeanUtils.copyProperties(e, convenerVo);

                List<ConvenerLikes> myLikes = likes.stream()
                        .filter(l -> Objects.equals(l.getConvenerId(), e.getCid()))
                        .peek(like -> {
                            if (like.getUserName().equals(principal.getName())) {
                                convenerVo.setLikes(true);
                            }
                        }).collect(Collectors.toList());

                convenerVo.setConvenerLikes(myLikes);
                Set<Object> users = redisService.sMembers(ChatConstant.CHAT_GROUP_ONLINE_KEY + convenerVo.getCid());
                if (CollUtil.isNotEmpty(users)) {
                    convenerVo.setOnlineUser(users.size());
                }
                convenerVo.setPaymentType(ConvenerPaymentType.of(e.getPaymentType()));
                convenerVo.setShopDetail(JSONUtil.toBean(e.getShopDetail(), ShopDetailVo.class));
                return convenerVo;
            }).collect(Collectors.toList());
            PageInfo<ConvenerVo> pageInfo = new PageInfo<>(convenerVos);
            return CommonResult.success(pageInfo);
        }
        return CommonResult.success(list);

    }

    /**
     * 列表
     */
    @ApiOperation("我发布的召集令列表")
    @GetMapping("/list/{userId}")
    public CommonResult myConvenerList(@RequestParam(required = false, defaultValue = "1") Integer pageNum,
                                       @RequestParam(required = false, defaultValue = "10") Integer pageSize,
                                       @PathVariable("userId") String userId) {
        PageHelper.startPage(pageNum, pageSize);
        List<Convener> list = convenerService.list(new QueryWrapper<Convener>().lambda()
                .eq(Convener::getUserId, userId)
                .orderByDesc(Convener::getStartTime)
        );
        if (CollUtil.isNotEmpty(list)) {
            List<Integer> cIds = list.stream().map(Convener::getCid).collect(Collectors.toList());
            List<ConvenerLikes> likes = convenerLikesService.list(new QueryWrapper<ConvenerLikes>().lambda().in(ConvenerLikes::getConvenerId, cIds));
            List<ConvenerVo> convenerVos = list.stream().map(e -> {
                ConvenerVo convenerVo = new ConvenerVo();
                BeanUtils.copyProperties(e, convenerVo);
                List<ConvenerLikes> myLikes = likes.stream().filter(l -> Objects.equals(l.getConvenerId(), e.getCid()))
                        .peek(like -> {
                            if (String.valueOf(like.getUserId()).equals(userId)) {
                                convenerVo.setLikes(true);
                            }
                        })
                        .collect(Collectors.toList());
                convenerVo.setConvenerLikes(myLikes);
                Set<Object> users = redisService.sMembers(ChatConstant.CHAT_GROUP_ONLINE_KEY + convenerVo.getCid());
                if (CollUtil.isNotEmpty(users)) {
                    convenerVo.setOnlineUser(users.size());
                }
                convenerVo.setPaymentType(ConvenerPaymentType.of(e.getPaymentType()));
                convenerVo.setShopDetail(JSONUtil.toBean(e.getShopDetail(), ShopDetailVo.class));
                return convenerVo;
            }).collect(Collectors.toList());
            PageInfo<ConvenerVo> pageInfo = new PageInfo<>(convenerVos);
            return CommonResult.success(pageInfo);
        }
        return CommonResult.success(list);
    }


    /**
     * 列表
     */
    @ApiOperation("我加入的召集令列表")
    @GetMapping("/list/join/{userId}")
    public CommonResult myJoinConvenerList(@RequestParam(required = false, defaultValue = "1") Integer pageNum,
                                       @RequestParam(required = false, defaultValue = "10") Integer pageSize,
                                       @PathVariable("userId") String userId) {

        PageInfo<ConvenerVo> vos = convenerService.getJoinConvener(userId, pageNum, pageSize);

        return CommonResult.success(vos);
    }

    /**
     * 信息
     */
    @ApiOperation("召集令详情")
    @GetMapping("/info/{cid}")
    public CommonResult info(Principal principal, @PathVariable("cid") Integer cid) {

        Convener convener = convenerService.getById(cid);
        List<ConvenerLikes> list = convenerLikesService.list(new QueryWrapper<ConvenerLikes>().lambda().eq(ConvenerLikes::getConvenerId, cid));
        if (convener != null) {
            ConvenerVo convenerVo = new ConvenerVo();
            BeanUtils.copyProperties(convener, convenerVo);
            convenerVo.setShopDetail(JSONUtil.toBean(convener.getShopDetail(), ShopDetailVo.class));
            convenerVo.setConvenerLikes(list);

            convenerVo.setPaymentType(ConvenerPaymentType.of(convener.getPaymentType()));

            if (convenerVo.getUserName().equals(principal.getName())) {
                convenerVo.setLikes(true);
            }
            Set<Object> users = redisService.sMembers(ChatConstant.CHAT_GROUP_ONLINE_KEY + convenerVo.getCid());
            if (CollUtil.isNotEmpty(users)) {
                convenerVo.setOnlineUser(users.size());
            }
            return CommonResult.success(convenerVo);
        }

        return CommonResult.failed("不存在数据！");
    }


    /**
     * 发起召集信息
     *
     * @return
     */
    @ApiOperation("发起召集")
    @PostMapping("/save")
    public CommonResult save(Principal principal, @Valid @RequestBody ConvenerCreateParams createParams) {

        if (principal == null) {
            throw new ApiException(ResultCode.UNAUTHORIZED);
        }
        // 发起召集
        Convener convener = convenerService.createConvener(principal.getName(), createParams);

        return CommonResult.success(convener != null);
    }

    /**
     * 确认参与人
     *
     * @param id
     * @return
     */
    @ApiOperation("确认参与人")
    @PostMapping("/affirm/{id}")
    public CommonResult affirm(Principal principal, @PathVariable Integer id, @RequestBody Long[] ids) {

        Convener convener = convenerService.getById(id);

        List<JoinConvener> joinConveners = joinConvenerService.list(new QueryWrapper<JoinConvener>().lambda()
                .eq(JoinConvener::getConvenerId, id)
                .eq(JoinConvener::getStatus, JoinConvenerType.SIGNUP.getCode()));

        if (convener != null) {

            if (principal == null || !convener.getUserName().equals(principal.getName())) {
                throw new ApiException("权限不足");
            }

            if (convener.getMaxUser() <= joinConveners.size()) {
                throw new ApiException("人数超出活动上限");
            }

            boolean update = joinConvenerService.update(new UpdateWrapper<JoinConvener>().lambda()
                    .set(JoinConvener::getStatus, JoinConvenerType.SIGNUP.getCode())
                    .in(JoinConvener::getUserId, Arrays.asList(ids))
            );

            return CommonResult.success(update);
        }

        return CommonResult.failed("确认人数失败");
    }

    /**
     * 修改
     */
    @ApiOperation("召集令修改")
    @PutMapping("/update")
    public CommonResult update(@RequestBody Convener convener) {

        // TODO 修改推送日期
        convenerService.updateById(convener);

        return CommonResult.success();
    }

    /**
     * 撤销召集令
     */
    @Transactional
    @ApiOperation("撤销召集令")
    @GetMapping("/revocation/{convenerId}")
    public CommonResult revocation(Principal principal, @PathVariable Integer convenerId) {

        boolean a = convenerService.update(new UpdateWrapper<Convener>().lambda()
                .set(Convener::getConvenerStatus, ConvenerStatus.REVOCATION.getCode())
                .eq(Convener::getCid, convenerId)
                .eq(Convener::getUserName, principal.getName())
        );

        return CommonResult.success(a);
    }


    /**
     * 暂停召集令
     */
    @ApiOperation("暂停召集令")
    @GetMapping("/cancel/{convenerId}")
    public CommonResult cancel(Principal principal, @PathVariable Integer convenerId) {

        boolean a = convenerService.update(new UpdateWrapper<Convener>().lambda()
                .set(Convener::getConvenerStatus, ConvenerStatus.PAUSE.getCode())
                .eq(Convener::getCid, convenerId)
                .eq(Convener::getUserName, principal.getName())
        );

        return CommonResult.success(a);
    }

    /**
     * 暂停召集令
     */
    @ApiOperation("停止召集令")
    @GetMapping("/stop/{convenerId}")
    public CommonResult stop(Principal principal, @PathVariable Integer convenerId) {

        boolean a = convenerService.update(new UpdateWrapper<Convener>().lambda()
                .set(Convener::getConvenerStatus, ConvenerStatus.STOP.getCode())
                .eq(Convener::getCid, convenerId)
                .eq(Convener::getUserName, principal.getName())
        );

        return CommonResult.success(a);
    }
    /**
     * 开始召集令
     */
    @ApiOperation("开始召集令活动")
    @GetMapping("/start/{convenerId}")
    public CommonResult start(Principal principal, @PathVariable Integer convenerId) {

        if (principal == null) {
            throw new ApiException(ResultCode.UNAUTHORIZED);
        }
        UserOrderInfoVo userorder = convenerService.startConvener(principal.getName(), convenerId);


        return CommonResult.success(userorder);
    }

    /**
     * 召集令进行的状态
     */
    @ApiOperation("召集令进行的状态")
    @GetMapping("/status/{convenerId}")
    public CommonResult check(Principal principal, @PathVariable Integer convenerId) {

        Convener convener = convenerService.getById(convenerId);
        if (convener != null) {
            return CommonResult.success(convener.getConvenerStatus());
        }
        return CommonResult.failed("无召集令信息");

    }

    /**
     * 是否能进入召集令房间
     */
    @ApiOperation("是否能进入召集令")
    @GetMapping("/join/{convenerId}")
    public Boolean joinConvener(Principal principal, @PathVariable Integer convenerId) {

        Convener convener = convenerService.getById(convenerId);

        if (convener != null) {
            if (Objects.equals(convener.getConvenerStatus(), ConvenerStatus.STOP.getCode())
                    || Objects.equals(convener.getConvenerStatus(), ConvenerStatus.UNDERWAY.getCode())
                    || Objects.equals(convener.getConvenerStatus(), ConvenerStatus.PAUSE.getCode())
            ) {
                JoinConvener joinConvener = joinConvenerService.getOne(new QueryWrapper<JoinConvener>().lambda()
                        .eq(JoinConvener::getConvenerId, convenerId)
                        .eq(JoinConvener::getUserName, principal.getName())
                );
                return joinConvener != null;
            }
            if (Objects.equals(convener.getConvenerStatus(), ConvenerStatus.REVOCATION.getCode())
            ) {
                return false;
            }
            return Objects.equals(convener.getConvenerStatus(), ConvenerStatus.NORMAL.getCode());
        }
        return false;
    }

    /**
     * 删除
     */
    @Transactional
    @ApiOperation("删除召集令")
    @DeleteMapping("/delete")
    public CommonResult delete(@RequestBody String[] cids) {

        convenerService.removeByIds(Arrays.asList(cids));

        groupChatService.removeByIds(Arrays.asList(cids));

        recentChatService.remove(new QueryWrapper<RecentChat>().lambda().in(RecentChat::getAccept, Arrays.asList(cids)));

        convenerLikesService.remove(new QueryWrapper<ConvenerLikes>().lambda().in(ConvenerLikes::getConvenerId, Arrays.asList(cids)));

        return CommonResult.success();
    }


    @ApiOperation("召集令点赞")
    @PostMapping("/likes")
    public CommonResult likes(@Valid @RequestBody ConvenerLikesParams params) {
        boolean result = convenerLikesService.likes(params);
        return CommonResult.success(result);
    }

    @ApiOperation("召集令取消点赞")
    @PostMapping("/dislikes")
    public CommonResult disLikes(@RequestBody ConvenerLikesParams params) {
        boolean result = convenerLikesService.dislikes(params);
        return CommonResult.success(result);
    }
}
